package com.yuhuihui.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 集合工具类
 *
 * @author yuhh
 * @date 2022-03-03 14:31:27
 */
public final class CollectionUtil {

    /** logger */
    private static final Logger logger = LoggerFactory.getLogger(CollectionUtil.class);

    private static final String EMPTY = "";

    /**
     * 以逗号拼接字符串
     *
     * @param collections 需要拼接的集合
     * @return {@link String }
     * @author yuhh
     * @date 2022-03-03 14:32:37
     */
    public static <T> String commaJoin(Collection<T> collections)  {
        return collections.stream().map(String::valueOf).collect(Collectors.joining(","));
    }

    /**
     * 集合转换为map
     *
     * @param beans       需要转换的集合
     * @param keyMapper   map的key
     * @param valueMapper map的value
     * @return {@link Map }<{@link K }, {@link U }>
     * @author yuhh
     * @date 2022-03-03 14:34:16
     */
    public static <T, K, U> Map<K, U> collectionToMap(Collection<T> beans, Function<T, K> keyMapper, Function<T, U> valueMapper) {

        if ( CollectionUtils.isEmpty(beans) || keyMapper == null || valueMapper == null) {
            return Collections.emptyMap();
        }

        return beans.stream().collect(Collectors.toMap(keyMapper, valueMapper));
    }

    /**
     * 集合转换为map
     *
     * @param beans     需要转换的集合
     * @param keyMapper map的key
     * @return {@link Map }<{@link R }, {@link T }>
     * @author yuhh
     * @date 2022-03-03 14:38:20
     */
    public static <T,R> Map<R, T> collectionToMapT(Collection<T> beans, Function<T, R> keyMapper) {

        if ( CollectionUtils.isEmpty(beans) || keyMapper == null) {
            return Collections.emptyMap();
        }

        return beans.stream().collect(Collectors.toMap(keyMapper, value -> value));
    }

    /**
     * 获取集合中的某个属性，以,号的方式拼接
     *
     * @param beans       集合列表
     * @param filedMapper filed使用的字段
     * @return {@link String }
     * @author yuhh
     * @date 2022-03-03 14:50:24
     */
    public static <T, K> String fieldValueMergeCommaSplit(Collection<T> beans, Function<T, K> filedMapper) {
        if (CollectionUtils.isEmpty(beans)) {
            return EMPTY;
        }
        return beans.stream()
                .map(filedMapper)
                .map(String::valueOf)
                .filter(value -> !ObjectUtils.isEmpty(value))
                .distinct()
                .collect(Collectors.joining(","));
    }

    /**
     * 从指定list中获取指定的参数的list
     *
     * @param beans  集合列表
     * @param mapper 指定的参数
     * @return {@link List<R> }
     * @author yuhh
     * @date 2022-03-03 14:40:21
     */
    public static <T, R> List<R> getParameterList(List<T> beans, Function<T, R> mapper) {
        return beans.stream().map(mapper).collect(Collectors.toList());
    }

    /**
     * 从指定list中获取指定的参数的非重复list
     *
     * @param beans  指定的list
     * @param mapper 指定的参数
     * @return {@link List }<{@link R }> 指定的参数的非重复list
     * @author yuhh
     * @date 2023-05-25 15:23:14
     */
    public static <T, R> List<R> getParameterDistinctList(List<T> beans, Function<T, R> mapper) {
        return beans.stream().map(mapper).distinct().collect(Collectors.toList());
    }

    /**
     * map转实体类
     *
     * @param map 需要转换的map
     * @param cls 需要转换成的实体类
     * @return {@link T }
     * @author yuhh
     * @date 2022-03-03 14:42:20
     */
    public static  <T> T mapToObject(Map<String, Object> map, Class<T> cls){
        if (CollectionUtils.isEmpty(map)){
            return null;
        }
        try {
            T t = cls.newInstance();
            map.forEach((k, v) -> {
                try {
                    // 根据code获取相应属性的set/get方法
                    PropertyDescriptor pd = new PropertyDescriptor(k, cls);
                    // 获取set方法
                    Method method = pd.getWriteMethod();
                    method.invoke(t, ConverterUtil.convert(pd.getPropertyType(), String.valueOf(v)));
                } catch (Exception e) {
                    logger.error("实体类赋值出现异常", e);
                }
            });
            return t;
        } catch (Exception e) {
            logger.error("初始化实体类出现异常", e);
        }
        return null;
    }

    /**
     * bigDecimal相加
     *
     * @param beans  需要操作的的列表
     * @param mapper 指定字段
     * @return {@link BigDecimal } 相加后的值
     * @author yuhh
     * @date 2022-09-19 13:44:22
     */
    public static <T> BigDecimal bigDecimalAdd(List<T> beans, Function<T, BigDecimal> mapper){
        if ( CollectionUtils.isEmpty(beans) || mapper == null) {
            return BigDecimal.ZERO;
        }
        return beans.stream().map(mapper).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 获取指定列表根据指定字段分组后的数据
     *
     * @param beans  需要分组的列表
     * @param mapper 指定字段
     * @return {@link Map }<{@link R }, {@link List }<{@link T }>> 分组后的数据
     * @author yuhh
     * @date 2023-05-25 15:23:37
     */
    public static <T, R> Map<R, List<T>> groupingBy(List<T> beans, Function<T, R> mapper){
        if ( CollectionUtils.isEmpty(beans) || mapper == null) {
            return Collections.emptyMap();
        }
        return beans.stream().collect(Collectors.groupingBy(mapper));
    }

    /**
     * 对象转list
     *
     * @param t 需要转换的对象
     * @return java.util.List<T> 转换好后的list
     * @author yuhh
     * @date 2024-08-26 11:20:35
     */
    public static <T> List<T> objectToList(T t){
        List<T> list = new ArrayList<>();
        list.add(t);
        return list;
    }
}
